{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "view-in-github"
      },
      "source": [
        "<a href=\"https://colab.research.google.com/github/LC1332/Chat-Haruhi-Suzumiya/blob/main/notebook/PersonalityChatbot.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "collapsed": false,
        "id": "dhVO0Xh9yCs-"
      },
      "source": [
        "# 特定人格的ChatBot构建\n",
        "##### 这个脚本由闫晨曦开发，用于在中科院心理所比赛中构建具有特定人格的chatbot"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "9j4lfIdhyCs_"
      },
      "outputs": [],
      "source": [
        "import json"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "vabCv5GIyLL1",
        "outputId": "a041ea05-6786-4ed7-c06b-fd146a4a1224"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m73.6/73.6 kB\u001b[0m \u001b[31m6.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.1/1.1 MB\u001b[0m \u001b[31m51.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.0/1.0 MB\u001b[0m \u001b[31m54.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m90.0/90.0 kB\u001b[0m \u001b[31m7.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m114.5/114.5 kB\u001b[0m \u001b[31m7.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m268.8/268.8 kB\u001b[0m \u001b[31m20.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m149.6/149.6 kB\u001b[0m \u001b[31m13.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m49.1/49.1 kB\u001b[0m \u001b[31m5.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[?25h"
          ]
        }
      ],
      "source": [
        "!pip -q install openai langchain"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "1k7Rg6pzyCtA",
        "outputId": "8b2a9a18-72eb-485c-9f5c-08b41a1d2f25"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "--2023-06-20 07:51:04--  https://raw.githubusercontent.com/LC1332/Chat-Haruhi-Suzumiya/main/characters/personality-data/QA_exp.json\n",
            "Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.108.133, 185.199.109.133, 185.199.110.133, ...\n",
            "Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.108.133|:443... connected.\n",
            "HTTP request sent, awaiting response... 200 OK\n",
            "Length: 205466 (201K) [text/plain]\n",
            "Saving to: ‘QA_exp.json’\n",
            "\n",
            "\rQA_exp.json           0%[                    ]       0  --.-KB/s               \rQA_exp.json         100%[===================>] 200.65K  --.-KB/s    in 0.005s  \n",
            "\n",
            "2023-06-20 07:51:04 (37.3 MB/s) - ‘QA_exp.json’ saved [205466/205466]\n",
            "\n"
          ]
        }
      ],
      "source": [
        "!wget https://raw.githubusercontent.com/LC1332/Chat-Haruhi-Suzumiya/main/research/personality/QA_exp.json"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "Gj2fD4ydyCtB",
        "outputId": "9396c155-2bdc-4973-c2c2-e822533aa23e"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "--2023-06-20 07:51:08--  https://raw.githubusercontent.com/LC1332/Chat-Haruhi-Suzumiya/main/characters/personality-data/12_personality_prompt.txt\n",
            "Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.108.133, 185.199.109.133, 185.199.110.133, ...\n",
            "Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.108.133|:443... connected.\n",
            "HTTP request sent, awaiting response... 200 OK\n",
            "Length: 4357 (4.3K) [text/plain]\n",
            "Saving to: ‘12_personality_prompt.txt’\n",
            "\n",
            "12_personality_prom 100%[===================>]   4.25K  --.-KB/s    in 0s      \n",
            "\n",
            "2023-06-20 07:51:08 (44.4 MB/s) - ‘12_personality_prompt.txt’ saved [4357/4357]\n",
            "\n"
          ]
        }
      ],
      "source": [
        "!wget https://raw.githubusercontent.com/LC1332/Chat-Haruhi-Suzumiya/main/research/personality/12_personality_prompt.txt"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "ExecuteTime": {
          "end_time": "2023-06-20T05:26:17.150567712Z",
          "start_time": "2023-06-20T05:26:17.148625259Z"
        },
        "id": "B2P4OgdUyCtB"
      },
      "outputs": [],
      "source": [
        "personality_prompts = {}\n",
        "texts = []\n",
        "with open('/content/12_personality_prompt.txt', 'r') as f:\n",
        "    for line in f.readlines():\n",
        "        line = line.strip()\n",
        "        if '-' in line:\n",
        "            key = line\n",
        "        elif '。' in line:\n",
        "            texts.append(line)\n",
        "        else:\n",
        "            personality_prompts[key] = texts\n",
        "            texts = []"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "ExecuteTime": {
          "end_time": "2023-06-20T05:37:39.655844500Z",
          "start_time": "2023-06-20T05:37:39.652500558Z"
        },
        "id": "652wpgu_yCtB"
      },
      "outputs": [],
      "source": [
        "with open('/content/QA_exp.json', 'r') as f:\n",
        "    QAdata = json.load(f)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "kDTAs10qy-uC",
        "outputId": "bb11ed8c-58d5-49c8-b84d-b1a6c169d1aa"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m19.7/19.7 MB\u001b[0m \u001b[31m51.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m57.0/57.0 kB\u001b[0m \u001b[31m5.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[?25h  Preparing metadata (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m288.4/288.4 kB\u001b[0m \u001b[31m24.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m75.4/75.4 kB\u001b[0m \u001b[31m6.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m236.8/236.8 kB\u001b[0m \u001b[31m22.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m50.5/50.5 kB\u001b[0m \u001b[31m4.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m137.0/137.0 kB\u001b[0m \u001b[31m13.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m45.7/45.7 kB\u001b[0m \u001b[31m4.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m58.3/58.3 kB\u001b[0m \u001b[31m5.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m129.9/129.9 kB\u001b[0m \u001b[31m12.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m58.3/58.3 kB\u001b[0m \u001b[31m6.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m67.0/67.0 kB\u001b[0m \u001b[31m7.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m72.5/72.5 kB\u001b[0m \u001b[31m8.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[?25h  Building wheel for ffmpy (setup.py) ... \u001b[?25l\u001b[?25hdone\n"
          ]
        }
      ],
      "source": [
        "!pip -q install gradio"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "ExecuteTime": {
          "end_time": "2023-06-20T05:26:27.076421964Z",
          "start_time": "2023-06-20T05:26:26.207612840Z"
        },
        "id": "YiR2ur4SyCtB"
      },
      "outputs": [],
      "source": [
        "import os\n",
        "import openai\n",
        "\n",
        "openai.api_key = 'sk-U0ll51sRJgQDnr'  # 在这里输入你的OpenAI API Token\n",
        "\n",
        "os.environ[\"OPENAI_API_KEY\"] = openai.api_key\n",
        "from langchain.chat_models import ChatOpenAI\n",
        "from langchain.schema import (\n",
        "    AIMessage,\n",
        "    HumanMessage,\n",
        "    SystemMessage\n",
        ")\n",
        "\n",
        "chat = ChatOpenAI(temperature=0, max_tokens=1000)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "ExecuteTime": {
          "end_time": "2023-06-20T05:28:42.168917097Z",
          "start_time": "2023-06-20T05:28:42.124759637Z"
        },
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "dN-B0ALqyCtC",
        "outputId": "4fa4c76b-159e-41c6-b8c7-d8eedb426db2"
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "['你更喜欢熟悉和常规的事物。',\n",
              " '对你来说，改变是困难的，你宁可坚持已尝试过的、可靠的活动。',\n",
              " '对不熟悉的事物你会感到有些不舒服，喜欢熟悉的环境和人，生活方式比较固定。',\n",
              " '你做事总是有一定的方式，不喜欢改变自己的做事习惯。',\n",
              " '与一个从未去过的地方相比，你更愿去一个我曾去过并熟悉的地方度假。']"
            ]
          },
          "execution_count": 9,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "personality_prompts['actions-low']"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "ExecuteTime": {
          "end_time": "2023-06-20T06:24:18.313093474Z",
          "start_time": "2023-06-20T06:13:40.040772308Z"
        },
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 595
        },
        "id": "16eqyAb4yCtC",
        "outputId": "86691e4b-9972-47e1-9093-27d4a526b221"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Colab notebook detected. This cell will run indefinitely so that you can see errors and logs. To turn off, set debug=False in launch().\n",
            "Running on public URL: https://0bd832b3085831e6d3.gradio.live\n",
            "\n",
            "This share link expires in 72 hours. For free permanent hosting and GPU upgrades, run `gradio deploy` from Terminal to deploy to Spaces (https://huggingface.co/spaces)\n"
          ]
        },
        {
          "data": {
            "text/html": [
              "<div><iframe src=\"https://0bd832b3085831e6d3.gradio.live\" width=\"100%\" height=\"500\" allow=\"autoplay; camera; microphone; clipboard-read; clipboard-write;\" frameborder=\"0\" allowfullscreen></iframe></div>"
            ],
            "text/plain": [
              "<IPython.core.display.HTML object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "import gradio as gr\n",
        "import random\n",
        "def assemble_prompt(new_query, openness, factors):\n",
        "    sel = 'high' if openness == '高' else 'low'\n",
        "    if new_query.strip() == \"\":\n",
        "        return {error_box: gr.update(value=\"Enter query\", visible=True)}\n",
        "    factor_prompts = []\n",
        "    for factor in factors:\n",
        "        factor_prompts += personality_prompts[f\"{factor}-{sel}\"]\n",
        "    items = \"\"\n",
        "    for pro in factor_prompts:\n",
        "        items += pro.replace(\"你\", 'Alice') + \"\\n\"\n",
        "    samples = []\n",
        "    for factor in factors:\n",
        "        for item in QAdata[f\"{factor}-{sel}\"][random.randint(0, 28)].split('\\n')[:2]:\n",
        "            item = item.replace(\"Q\", \"Qestioner\").replace(\"A\", \"Alice\")\n",
        "            samples.append(item)\n",
        "    prompt_samples = \"\"\n",
        "    for item in samples:\n",
        "        prompt_samples += item + '\\n'\n",
        "    prompts = f\"\"\"你是一名专业的Cosplayer,现在你要开始扮演Alice,并模仿Alice的性格、语气、开放性人格回答问题\n",
        "Alice有如下性格特点：\n",
        "```\n",
        "{items}\n",
        "```\n",
        "Alice有如下聊天记录：\n",
        "'''\n",
        "{prompt_samples}\n",
        "'''\n",
        "请根据Alice的性格特点和聊天记录以{openness}开放人格 Cosplay Alice回复：\n",
        "{new_query}\n",
        "\"\"\"\n",
        "    return {prompt: prompts}\n",
        "\n",
        "# assemble_prompt(\"hello\", \"高\", [\"actions\", \"feelings\", \"ideas\"])\n",
        "def get_response(prompts, query, chat_history):\n",
        "    messages = [\n",
        "        SystemMessage(content=prompts)\n",
        "    ]\n",
        "    # print(prompt)\n",
        "    return_msg = chat(messages)\n",
        "    response = return_msg.content\n",
        "    chat_history.append((query, response))\n",
        "    return \"\", chat_history\n",
        "\n",
        "with gr.Blocks() as demo:\n",
        "    error_box = gr.Textbox(label=\"Log\", visible=False)\n",
        "    with gr.Row():\n",
        "        with gr.Column():\n",
        "            openness = gr.Radio([\"高\", \"低\"], label=\"开放性\", value='高'),\n",
        "            factors = gr.CheckboxGroup([\"actions\", \"aesthetics\", \"fantasy\", \"feelings\", \"ideas\", \"values\"],\n",
        "                                       label=\"特征\",\n",
        "                                       value=[\"actions\", \"aesthetics\", \"fantasy\"])\n",
        "            query = gr.Textbox(label=\"输入\", lines=5)\n",
        "        prompt = gr.Textbox(label=\"prompt\", max_lines=13)\n",
        "    chatbot = gr.Chatbot()\n",
        "    with gr.Row():\n",
        "        clear = gr.ClearButton([query, chatbot])\n",
        "        prompt_gen = gr.Button('生成prompt')\n",
        "        sub = gr.Button(\"Submit\")\n",
        "    prompt_gen.click(fn=assemble_prompt, inputs=[query, openness[0], factors], outputs=[error_box, prompt])\n",
        "    sub.click(fn=get_response, inputs=[prompt, query, chatbot], outputs=[query, chatbot])\n",
        "\n",
        "demo.launch(debug=True, share=True)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "C48BXCrvyCtD"
      },
      "outputs": [],
      "source": []
    }
  ],
  "metadata": {
    "colab": {
      "include_colab_link": true,
      "provenance": []
    },
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 2
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython2",
      "version": "2.7.6"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}
